package com.lnn.springBase.nc;

import java.io.IOException;
import java.io.RandomAccessFile;

public class RadarDataParser {
    // 反射率索引数组，用于将读取的数据索引转换为对应的反射率值
    private static final float[] REFLECTIVITY_INDEX = {-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65};
    // 数据的分辨率，单位是公里，这里为 1 公里
    private static final float M_RESOLUTE = 1.0f;
    // 图像中心点在矩阵中的 x 坐标
    private static final float CENTER_X = 1500;
    // 图像中心点在矩阵中的 y 坐标
    private static final float CENTER_Y = 1500;
    // 图像中心点的经度
    private static final float CENTER_LON = 119.0f;
    // 图像中心点的纬度
    private static final float CENTER_LAT = 33.0f;
    // 文件头和数据区的分隔标志，当读取到该值时，表示文件头读取结束
    private static final float DATA_SEPARATOR = 10000;

    public static void main(String[] args) {
        // 示例文件名，根据实际情况修改，体现了华东雷达的数据文件命名
        String filePath = "D:\\lnnxy\\Documents\\WeChat Files\\qq735962011\\FileStorage\\File\\2025-04\\RadJw202501200006.00.37.dat";
        try {
            // 调用 parseRadarData 方法解析雷达数据文件
            parseRadarData(filePath);
        } catch (IOException e) {
            // 捕获并打印可能出现的 IO 异常信息
            e.printStackTrace();
        }
    }

    // 解析雷达数据文件的主要方法
    public static void parseRadarData(String filePath) throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(filePath, "r")) {
            // 恢复文件头解析逻辑
            String fileName = readString(raf);
            System.out.println("华东雷达数据文件名: " + fileName);
            // // 新增文件头读取逻辑，直到遇到分隔符10000
            // while (true) {
            //     float headerValue = raf.readFloat();
            //     if (headerValue == DATA_SEPARATOR) {
            //         break;
            //     }
            //     // 此处可以添加其他文件头字段的解析逻辑
            // }
            // 解析数据区（修复逆向读取逻辑）
            long dataStartPos = raf.getFilePointer();  // 记录数据区起始位置
            long fileSize = raf.length();
            int recordLength = 4*3; // 每个记录包含3个int（12字节）

            // 计算有效数据范围（从数据区开始到文件末尾）
            for (long pos = fileSize - recordLength; pos >= dataStartPos; pos -= recordLength) {
                raf.seek(pos);

                int x = raf.readInt();
                int y = raf.readInt();
                int index = raf.readInt();

                // 添加索引范围校验
                if (index < 0 || index >= REFLECTIVITY_INDEX.length) {
                    System.err.println("发现无效索引值: " + index + "，已跳过该记录");
                    continue;
                }
                System.out.printf("坐标 (x: %d, y: %d)", x, y);
                float reflectivity = REFLECTIVITY_INDEX[index];
                PointF point = ActToPro(x, y, CENTER_LON, CENTER_LAT, CENTER_X, CENTER_Y, M_RESOLUTE);
                //System.out.printf("坐标 (x: %d, y: %d), 反射率: %.1f, 经纬度 (lon: %.6f, lat: %.6f)%n",
                  //      x, y, reflectivity, point.x, point.y);
            }
        }
    }

    // 修改字符串读取方法适配RandomAccessFile
    private static String readString(RandomAccessFile raf) throws IOException {
        StringBuilder sb = new StringBuilder();
        byte b;
        while ((b = raf.readByte()) != '\0') {
            sb.append((char) b);
        }
        return sb.toString();
    }

    // 将相对于中心点的 x、y 坐标转换为经纬度的方法
    public static PointF ActToPro(float posx, float posy, float lon0, float lat0, float m_centX, float m_centY, float m_Resolute) {
        float lon, lat;
        float p, c;
        // 将中心点的经度从度转换为弧度，因为后续三角函数计算需要使用弧度制
        lon0 = (float) (lon0 * Math.PI / 180);
        // 将中心点的纬度从度转换为弧度
        lat0 = (float) (lat0 * Math.PI / 180);
        // 计算待转换点相对于中心点的 x 方向距离，并转换为以地球半径为单位的距离
        posx = (float) ((posx - m_centX) * m_Resolute / 6370.0);
        // 计算待转换点相对于中心点的 y 方向距离，并转换为以地球半径为单位的距离
        posy = (float) ((m_centY - posy) * m_Resolute / 6370.0);
        // 计算待转换点与中心点的距离
        p = (float) Math.sqrt(Math.pow(posx, 2) + Math.pow(posy, 2));
        // 计算该距离对应的角度
        c = (float) Math.atan(p);
        // 使用球面几何公式计算待转换点的经度
        lon = lon0 + (float) Math.atan(posx * Math.sin(c) / (p * Math.cos(lat0) * Math.cos(c) - posy * Math.sin(lat0) * Math.sin(c)));
        // 使用球面几何公式计算待转换点的纬度
        lat = (float) Math.asin(Math.cos(c) * Math.sin(lat0) + posy * Math.sin(c) * Math.cos(lat0) / p);
        // 将计算得到的纬度从弧度转换为度
        lat = (float) (lat * 180 / Math.PI);
        // 将计算得到的经度从弧度转换为度
        lon = (float) (lon * 180 / Math.PI);
        // 返回包含经纬度的 PointF 对象
        return new PointF(lon, lat);
    }
}

// PointF 类用于表示一个二维点，包含 x 和 y 坐标，在 ActToPro 方法中用于返回经纬度
class PointF {
    float x;
    float y;

    // 构造函数，用于初始化 PointF 对象的 x 和 y 坐标
    public PointF(float x, float y) {
        this.x = x;
        this.y = y;
    }
}
